package com.beluga.core.util;

import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author iron.guo
 */
public interface IMapIfUtil {

    IMapIfUtil build = new IMapIfUtil() {
    };

    default <K, R> R mapIfFunDefaultNull(K key, Map<K, Function<K, R>> ruleMap) {
        return mapIfFunDefaultVal(key, null, ruleMap);
    }

    default <K, R> R mapIfFunDefaultVal(K key, R defaultVal, Map<K, Function<K, R>> ruleMap) {
        return ruleMap.containsKey(key) ? ruleMap.get(key).apply(key) : defaultVal;
    }

    default <K, R> R mapIfFunDefaultFun(K key, Function<K, R> defaultFun, Map<K, Function<K, R>> ruleMap) {
        return ruleMap.containsKey(key) ? ruleMap.get(key).apply(key) : defaultFun.apply(key);
    }

    default <K> void mapIfVoid(K key, Map<K, Consumer<K>> ruleMap) {
        if (ruleMap.containsKey(key)) {
            ruleMap.get(key).accept(key);
        }
    }

    default <K> void mapIfVoidDefault(K key, Consumer<K> defaultFun, Map<K, Consumer<K>> ruleMap) {
        if (ruleMap.containsKey(key)) {
            ruleMap.get(key).accept(key);
        } else {
            defaultFun.accept(key);
        }
    }

    default <K, R> R mapIfGetDefaultNull(K key, Map<K, Supplier<R>> ruleMap) {
        return mapIfGetDefaultVal(key, null, ruleMap);
    }

    default <K, R> R mapIfGetDefaultVal(K key, R defaultVal, Map<K, Supplier<R>> ruleMap) {
        return ruleMap.containsKey(key) ? ruleMap.get(key).get() : defaultVal;
    }

    default <K, R> R mapIfGetDefaultGet(K key, Supplier<R> defaultGet, Map<K, Supplier<R>> ruleMap) {
        return ruleMap.containsKey(key) ? ruleMap.get(key).get() : defaultGet.get();
    }

    default <K, P, R> R mapIfFunDefaultNullByKey(P param, K key, Map<K, Function<P, R>> ruleMap) {
        return mapIfFunDefaultValByKey(param, key, null, ruleMap);
    }

    default <K, P, R> R mapIfFunDefaultValByKey(P param, K key, R defaultVal, Map<K, Function<P, R>> ruleMap) {
        return ruleMap.containsKey(key) ? ruleMap.get(key).apply(param) : defaultVal;
    }

    default <K, P, R> R mapIfFunDefaultFunByKey(P param, K key, Function<P, R> defaultFun, Map<K, Function<P, R>> ruleMap) {
        return ruleMap.containsKey(key) ? ruleMap.get(key).apply(param) : defaultFun.apply(param);
    }

    default <K, P> void mapIfVoidByKey(P param, K key, Map<K, Consumer<P>> ruleMap) {
        if (ruleMap.containsKey(key)) {
            ruleMap.get(key).accept(param);
        }
    }

    default <K, P> void mapIfVoidDefaultByKey(P param, K key, Consumer<P> defaultFun, Map<K, Consumer<P>> ruleMap) {
        if (ruleMap.containsKey(key)) {
            ruleMap.get(key).accept(param);
        } else {
            defaultFun.accept(param);
        }
    }

    default <K, P extends Object, R> R mapIfFunDefaultNullByField(P param, Function<P, K> fieldKey, Map<K, Function<P, R>> ruleMap) {
        return mapIfFunDefaultValByField(param, fieldKey, null, ruleMap);
    }

    default <K, P extends Object, R> R mapIfFunDefaultValByField(P param, Function<P, K> fieldKey, R defaultVal, Map<K, Function<P, R>> ruleMap) {
        K k = fieldKey.apply(param);
        return ruleMap.containsKey(k) ? ruleMap.get(k).apply(param) : defaultVal;
    }

    default <K, P extends Object, R> R mapIfFunDefaultFunByField(P param, Function<P, K> fieldKey, Function<P, R> defaultFun, Map<K, Function<P, R>> ruleMap) {
        K k = fieldKey.apply(param);
        return ruleMap.containsKey(k) ? ruleMap.get(k).apply(param) : defaultFun.apply(param);
    }

    default <K, P extends Object> void mapIfVoidByField(P param, Function<P, K> fieldKey, Map<K, Consumer<P>> ruleMap) {
        K k = fieldKey.apply(param);
        if (ruleMap.containsKey(k)) {
            ruleMap.get(k).accept(param);
        }
    }

    default <K, P extends Object> void mapIfVoidDefaultByField(P param, Function<P, K> fieldKey, Consumer<P> defaultFun, Map<K, Consumer<P>> ruleMap) {
        K k = fieldKey.apply(param);
        if (ruleMap.containsKey(k)) {
            ruleMap.get(k).accept(param);
        } else {
            defaultFun.accept(param);
        }
    }
}